#include "encode_handler.h"
#include <iostream>
#include "tools.h"
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
}
using namespace std;

namespace lcf
{

    void EncodeHandler::Clear()
    {
        pktList_.Clear();
        unique_lock<mutex> lock(mtx_);
        while (!frameList_.empty())
        {
            av_frame_free(&frameList_.front());
            frameList_.pop_front();
        }
        curPts_ = -1;
        encoder_.Clear();
    }
    void EncodeHandler::Stop()
    {
        ThreadHandler::Stop();
        pktList_.Clear();
        unique_lock<mutex> lock(mtx_);
        while (!frameList_.empty())
        {
            av_frame_free(&frameList_.front());
            frameList_.pop_front();
        }
        encoder_.SetContext(nullptr);
        isOpen_ = false;
        if (timeBase_)
            delete timeBase_;
        timeBase_ = nullptr;
    }

    /// 打开解码器
    bool EncodeHandler::Open(AVCodecParameters *para)
    {
        if (!para)
        {
            LOGERROR("para is null!");
            return false;
        }
        unique_lock<mutex> lock(mtx_);
        isOpen_ = false;
        auto context = encoder_.CreateContext(para->codec_id, false);
        if (!context)
        {
            LOGERROR("encoder_.Create failed!");
            return false;
        }
        // 复制视频参数
        avcodec_parameters_to_context(context, para);
        encoder_.SetContext(context);
        if (!encoder_.Open())
        {
            LOGERROR("encoder_.Open() failed!");
            return false;
        }
        LOGINFO("Open decode success!");
        isOpen_ = true;
        return true;
    }

    // 责任链处理函数
    void EncodeHandler::HandleTask(AVPacket *pkt)
    {
        cout << "#" << flush;

        if (!pkt || pkt->stream_index != streamIndex_) // 判断是否是视频
        {
            return;
        }
        pktList_.Push(pkt);
        if (blockSize_ <= 0)
            return;
        while (!isExit_)
        {
            if (pktList_.Size() > blockSize_)
            {
                MSleep(1);
                continue;
            }
            break;
        }
    }

    // 线程主函数
    void EncodeHandler::Main()
    {
        {
            std::unique_lock<std::mutex> lock(mtx_);
            if (!frame_)
                frame_ = av_frame_alloc();
        }
        while (!isExit_)
        {
            // 暂停
            if (IsPause())
            {
                MSleep(1);
                continue;
            }
            // 同步
            while (!isExit_)
            {
                if (syncPts_ >= 0 && curPts_ > syncPts_)
                {
                    MSleep(1);
                    continue;
                }
                break;
            }

            AVPacket *pkt = pktList_.Pop();
            if (!pkt || !frame_)
            {
                this_thread::sleep_for(1ms);
                continue;
            }
            // 开始解码
            encoder_.Encode(frame_);
            av_packet_free(&pkt);
            cout << "@" << flush;
            needView_ = true;
            curPts_ = frame_->pts;
            // 转换成毫秒
            if (timeBase_)
            {
                curMs_ = av_rescale_q(frame_->pts, *timeBase_,
                                      {1, 1000});
            }
            if (isCache_)
            {
                auto f = av_frame_alloc();
                av_frame_ref(f, frame_); // 引用计数加1
                frameList_.push_back(f);
            }

            this_thread::sleep_for(1ms);
        }
        {
            std::unique_lock<std::mutex> lock(mtx_);
            if (frame_)
                av_frame_free(&frame_);
        }
    }
}
